/**
 * Created by admin on 2017/1/7.
 * 检测物体碰撞
 */
$(function () {
  "use strict";

  var READIED = 0, STARTING = 1, PAUSE = 2, GAME_OVER = 3;

  (function () {
    var lastTime = 0;
    var vendors = ['webkit', 'moz'];
    for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
      window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
      window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] ||
        window[vendors[x] + 'CancelRequestAnimationFrame'];
    }
    if (!window.requestAnimationFrame) {
      window.requestAnimationFrame = function (callback) {
        var currTime = new Date().getTime();
        var timeToCall = Math.max(0, 16.7 - (currTime - lastTime));
        var id = window.setTimeout(function () {
          callback(currTime + timeToCall);
        }, timeToCall);
        lastTime = currTime + timeToCall;
        return id;
      };
    }
    if (!window.cancelAnimationFrame) {
      window.cancelAnimationFrame = function (id) {
        clearTimeout(id);
      };
    }
  }());

  function App(config) {
    this.kep = document.getElementById('kep');
    this.canvas = document.getElementById('canvas');
    this.WIDTH = document.body.clientWidth;
    this.HEIGHT = document.body.scrollHeight;

    this.config = config;
    this.fruit = config.fruit;
    this.score = 0;
    this.state = READIED;

    this._init();
  }

  /**
   * 生成一堆水果
   * @param fruit 水果的基本参数
   * @returns {Array} 返回数组
   */
  App.prototype.fruits = function (fruit) {
    var dom = [],
      num = fruit.num || 10,
      name = fruit.name || 'fruit',
      width = fruit.width || 40,
      height = fruit.height || 40,
      maxHeight = this.HEIGHT - height,
      maxWidth = this.WIDTH - width;

    for (var i = 0; i < num; i++) {
      var el = $('<div class="item ' + name + ' tag_' + i + '" data-id="tag_' + i + '"></div>');
      el.css({
        width: width,
        height: height,
        top: Math.random() * (maxHeight * .8 + 1),
        left: Math.random() * (maxWidth + 1)
      });
      dom.push(el[0]);
    }

    return dom;
  };


  /**
   * 生成场景
   */
  App.prototype.scene = function () {
    var _this = this;
    var fruits = this.fruits(this.fruit);
    $(this.canvas).append(fruits);

    this.binEvent(this.kep).timeLine(fruits, function (ele) {
      $('.' + ele.id).remove();
      _this.score++;
    }, function () {
      alert('战斗力达到' + _this.score);
    });
  };


  /**
   * 时间轴
   * @param fruits
   * @param callback 当获取到被碰撞的元素时
   * @param endCallBack 当队列执行完毕时
   * @returns {App}
   */
  App.prototype.timeLine = function (fruits, callback, endCallBack) {
    var _this = this,
      startTime = Date.now(),
      distance = _this.HEIGHT,
      T = _this.config.time*1000;
    requestAnimationFrame(function step() {
      var p = Math.min(1, (Date.now() - startTime) / T);
      _this.canvas.style.transform = 'translateY(' + (distance * p) + 'px)';

      fruits.forEach(function (ele) {
        _this.detection(_this.kep, ele, callback); // 碰撞检测
      });

      p < 1 ? requestAnimationFrame(step) : endCallBack();
    });
    return this;
  };


  /**
   * 添加监听事件， 监听篮子的移动
   * @param kep 篮子对象
   * @returns {App}
   */
  App.prototype.binEvent = function (kep) {
    var move = false;
    var limit = this.config.limit? this.HEIGHT - this.config.limit: 0;

    // 移动 kep
    var mousedown = function (e) {
      e.preventDefault();
      move = true;
    };
    var mousemove = function (e) {
      e.preventDefault();
      if (!move) return;
      if (e.touches) {
        e.clientY = e.touches[0].pageY;
        e.clientX = e.touches[0].pageX;
      }
      var clientY = e.clientY <= limit? limit: e.clientY;
      kep.style.top = clientY - kep.clientHeight / 2 + 'px';
      kep.style.left = e.clientX - kep.clientWidth / 2 + 'px';
    };
    var mouseup = function (e) {
      e.preventDefault();
      move = false;
      mousemove = null;
    };

    kep.addEventListener('touchstart', mousedown);
    kep.addEventListener('touchend', mouseup);
    document.addEventListener('touchmove', mousemove);

    kep.addEventListener('mousedown', mousedown);
    kep.addEventListener('mouseup', mouseup);
    document.addEventListener('mousemove', mousemove);

    return this;
  };


  /**
   * 检测是否和第一个物体发生碰撞， 并获取碰撞物
   * @param a
   * @param b 被测试碰撞的对象
   * @param callback
   */
  App.prototype.detection = function (a, b, callback) {
    a = this._toObj(a);
    b = this._toObj(b);
    if ((Math.abs(a.x - b.x) <= (a.w / 2 + b.w / 2)) && (Math.abs(a.y - b.y) <= (a.h / 2 + b.h / 2))) callback(b);
  };


  /**
   * 将DOM对象扩展成一个普通对象
   * @param ele
   * @returns {{el: *, id: string, x: *, y: *, w: number, h: number}}
   * @private
   */
  App.prototype._toObj = function (ele) {
    var $ele = $(ele);
    return {
      el: ele,
      id: ele.getAttribute('data-id'),
      x: $ele.offset().left + $ele.width() / 2,
      y: $ele.offset().top + $ele.height() / 2,
      w: $ele.width(),
      h: $ele.height()
    }
  };


  /**
   * 入口
   * @private
   */
  App.prototype._init = function () {
    this.scene();
  };


  /**
   * 开始方法
   */
  App.prototype.paly = function () {
    this.state = STARTING;

  };

  /**
   * 暂停方法
   */
  App.prototype.pause = function () {
    this.state = PAUSE;

  };


  /**
   * 执行
   * @type {App}
   */
  new App({
    time: 5,
    limit: 150,
    fruit: {
      name: 'fruit',
      num: 60,
      width: 40,
      height: 40
    }
  });
});